"""
交易执行引擎
"""
import asyncio
import logging
from datetime import datetime
from typing import Dict, List, Optional, Any
from dataclasses import dataclass
from enum import Enum

from ..core.config import settings
from ..core.database import db_manager
from ..services.risk_manager import risk_manager

logger = logging.getLogger(__name__)


class OrderStatus(Enum):
    """订单状态"""
    PENDING = "pending"
    FILLED = "filled"
    CANCELLED = "cancelled"
    REJECTED = "rejected"
    PARTIAL = "partial"


class TradeType(Enum):
    """交易类型"""
    BUY = "buy"
    SELL = "sell"


@dataclass
class Order:
    """订单"""
    order_id: str
    strategy_id: str
    symbol: str
    trade_type: TradeType
    quantity: int
    price: float
    amount: float
    status: OrderStatus
    created_at: datetime
    filled_at: Optional[datetime] = None
    commission: float = 0.0


class TradeEngine:
    """交易执行引擎"""
    
    def __init__(self):
        self.is_running = False
        self.pending_orders: Dict[str, Order] = {}
        self.completed_orders: Dict[str, Order] = {}
        self.order_counter = 0
        self._lock = asyncio.Lock()
        
        # 模拟交易模式
        self.simulation_mode = True
        self.fill_probability = 0.95  # 成交概率
        self.slippage = 0.001  # 滑点
        
        # 券商接口（模拟）
        self.broker = None
    
    async def start(self):
        """启动交易引擎"""
        try:
            logger.info("正在启动交易引擎...")
            
            # 初始化券商接口
            await self._initialize_broker()
            
            # 加载未完成订单
            await self._load_pending_orders()
            
            self.is_running = True
            logger.info("交易引擎启动完成")
            
        except Exception as e:
            logger.error(f"交易引擎启动失败: {e}")
            raise
    
    async def stop(self):
        """停止交易引擎"""
        try:
            logger.info("正在停止交易引擎...")
            
            self.is_running = False
            
            # 保存订单状态
            await self._save_order_state()
            
            logger.info("交易引擎已停止")
            
        except Exception as e:
            logger.error(f"停止交易引擎失败: {e}")
    
    async def _initialize_broker(self):
        """初始化券商接口"""
        try:
            if settings.BROKER_TYPE == "模拟交易":
                self.simulation_mode = True
                logger.info("交易引擎运行在模拟模式")
            else:
                # 这里可以初始化真实的券商接口
                # 如 easytrader 等
                self.simulation_mode = False
                logger.info(f"交易引擎连接到券商: {settings.BROKER_TYPE}")
                
        except Exception as e:
            logger.error(f"初始化券商接口失败: {e}")
            self.simulation_mode = True
    
    async def _load_pending_orders(self):
        """加载未完成订单"""
        try:
            # 从数据库加载未完成的订单
            trades = await db_manager.get_trade_records()
            
            for trade in trades:
                if trade["status"] == "pending":
                    order = Order(
                        order_id=trade["order_id"],
                        strategy_id=trade["strategy_id"],
                        symbol=trade["symbol"],
                        trade_type=TradeType(trade["trade_type"]),
                        quantity=trade["quantity"],
                        price=trade["price"],
                        amount=trade["amount"],
                        status=OrderStatus.PENDING,
                        created_at=trade["trade_time"]
                    )
                    
                    self.pending_orders[order.order_id] = order
            
            logger.info(f"已加载 {len(self.pending_orders)} 个未完成订单")
            
        except Exception as e:
            logger.error(f"加载未完成订单失败: {e}")
    
    async def _save_order_state(self):
        """保存订单状态"""
        try:
            # 保存订单状态到数据库
            for order in self.pending_orders.values():
                await db_manager.save_trade_record({
                    "strategy_id": order.strategy_id,
                    "order_id": order.order_id,
                    "symbol": order.symbol,
                    "trade_type": order.trade_type.value,
                    "quantity": order.quantity,
                    "price": order.price,
                    "amount": order.amount,
                    "commission": order.commission,
                    "trade_time": order.created_at,
                    "status": order.status.value
                })
            
            logger.info("订单状态已保存")
            
        except Exception as e:
            logger.error(f"保存订单状态失败: {e}")
    
    def _generate_order_id(self) -> str:
        """生成订单ID"""
        self.order_counter += 1
        timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
        return f"ORD{timestamp}{self.order_counter:06d}"
    
    async def execute_signal(self, strategy_id: str, signal: Dict) -> Dict[str, Any]:
        """执行交易信号"""
        try:
            logger.info(f"策略 {strategy_id} 执行交易信号: {signal}")
            
            # 解析信号
            symbol = signal.get("symbol")
            action = signal.get("action")  # buy/sell
            quantity = signal.get("quantity", 100)  # 默认100股
            price = signal.get("price", 0.0)
            
            if not symbol or not action:
                return {
                    "success": False,
                    "error": "缺少必要的信号参数"
                }
            
            # 检查交易类型
            if action not in ["buy", "sell"]:
                return {
                    "success": False,
                    "error": f"无效的交易类型: {action}"
                }
            
            # 创建订单
            order_result = await self.create_order(
                strategy_id=strategy_id,
                symbol=symbol,
                trade_type=TradeType(action),
                quantity=quantity,
                price=price
            )
            
            return order_result
            
        except Exception as e:
            logger.error(f"执行交易信号失败: {e}")
            return {
                "success": False,
                "error": str(e)
            }
    
    async def create_order(self, strategy_id: str, symbol: str, trade_type: TradeType, 
                          quantity: int, price: float = 0.0) -> Dict[str, Any]:
        """创建订单"""
        try:
            # 生成订单ID
            order_id = self._generate_order_id()
            
            # 计算订单金额
            if price <= 0:
                # 如果没有指定价格，使用市价
                price = await self._get_current_price(symbol)
            
            amount = price * quantity
            
            # 创建订单
            order = Order(
                order_id=order_id,
                strategy_id=strategy_id,
                symbol=symbol,
                trade_type=trade_type,
                quantity=quantity,
                price=price,
                amount=amount,
                status=OrderStatus.PENDING,
                created_at=datetime.now()
            )
            
            # 风险检查
            risk_check = await risk_manager.check_trade_risk({
                "symbol": symbol,
                "trade_type": trade_type.value,
                "quantity": quantity,
                "price": price,
                "amount": amount
            })
            
            if not risk_check["allowed"]:
                order.status = OrderStatus.REJECTED
                logger.warning(f"订单 {order_id} 被风险检查拒绝: {risk_check['reason']}")
                
                return {
                    "success": False,
                    "order_id": order_id,
                    "error": risk_check["reason"],
                    "risks": risk_check["risks"]
                }
            
            # 保存订单
            async with self._lock:
                self.pending_orders[order_id] = order
            
            # 保存到数据库
            await db_manager.save_trade_record({
                "strategy_id": strategy_id,
                "order_id": order_id,
                "symbol": symbol,
                "trade_type": trade_type.value,
                "quantity": quantity,
                "price": price,
                "amount": amount,
                "commission": 0.0,
                "trade_time": order.created_at,
                "status": "pending"
            })
            
            logger.info(f"订单 {order_id} 创建成功: {symbol} {trade_type.value} {quantity}@{price}")
            
            # 异步执行订单
            asyncio.create_task(self._execute_order(order_id))
            
            return {
                "success": True,
                "order_id": order_id,
                "status": "pending"
            }
            
        except Exception as e:
            logger.error(f"创建订单失败: {e}")
            return {
                "success": False,
                "error": str(e)
            }
    
    async def _execute_order(self, order_id: str):
        """执行订单"""
        try:
            # 获取订单
            order = self.pending_orders.get(order_id)
            if not order:
                logger.error(f"订单 {order_id} 不存在")
                return
            
            logger.info(f"开始执行订单 {order_id}")
            
            if self.simulation_mode:
                # 模拟执行
                await self._simulate_order_execution(order)
            else:
                # 真实交易执行
                await self._real_order_execution(order)
            
        except Exception as e:
            logger.error(f"执行订单 {order_id} 失败: {e}")
    
    async def _simulate_order_execution(self, order: Order):
        """模拟订单执行"""
        try:
            # 模拟成交延迟
            await asyncio.sleep(1)
            
            # 模拟成交概率
            import random
            if random.random() > self.fill_probability:
                # 未成交
                order.status = OrderStatus.CANCELLED
                logger.info(f"订单 {order.order_id} 未成交")
            else:
                # 成交，添加滑点
                slippage = random.uniform(-self.slippage, self.slippage)
                filled_price = order.price * (1 + slippage)
                
                # 计算佣金（模拟）
                commission = order.amount * 0.00025  # 万分之二点五
                
                # 更新订单
                order.status = OrderStatus.FILLED
                order.filled_at = datetime.now()
                order.price = filled_price
                order.commission = commission
                
                logger.info(f"订单 {order.order_id} 成交: {order.symbol} {order.quantity}@{filled_price:.3f}")
                
                # 更新持仓
                await self._update_position(order)
                
                # 更新每日统计
                await risk_manager.update_daily_stats({
                    "symbol": order.symbol,
                    "trade_type": order.trade_type.value,
                    "quantity": order.quantity,
                    "price": filled_price,
                    "amount": order.amount - commission
                })
            
            # 移动订单状态
            async with self._lock:
                if order.order_id in self.pending_orders:
                    del self.pending_orders[order.order_id]
                self.completed_orders[order.order_id] = order
            
            # 更新数据库
            await db_manager.save_trade_record({
                "strategy_id": order.strategy_id,
                "order_id": order.order_id,
                "symbol": order.symbol,
                "trade_type": order.trade_type.value,
                "quantity": order.quantity,
                "price": order.price,
                "amount": order.amount,
                "commission": order.commission,
                "trade_time": order.created_at,
                "status": order.status.value
            })
            
        except Exception as e:
            logger.error(f"模拟订单执行失败: {e}")
    
    async def _real_order_execution(self, order: Order):
        """真实订单执行"""
        try:
            # 这里应该调用真实的券商API
            # 如 easytrader 等
            
            logger.warning("真实交易模式未实现，使用模拟模式")
            await self._simulate_order_execution(order)
            
        except Exception as e:
            logger.error(f"真实订单执行失败: {e}")
    
    async def _get_current_price(self, symbol: str) -> float:
        """获取当前价格"""
        try:
            # 这里应该从行情服务获取实时价格
            # 现在返回模拟价格
            return 3.0  # 模拟价格
            
        except Exception as e:
            logger.error(f"获取当前价格失败: {e}")
            return 0.0
    
    async def _update_position(self, order: Order):
        """更新持仓"""
        try:
            # 获取当前持仓
            positions = await db_manager.get_positions(order.strategy_id)
            
            # 查找对应持仓
            position = None
            for pos in positions:
                if pos["symbol"] == order.symbol:
                    position = pos
                    break
            
            if order.trade_type == TradeType.BUY:
                # 买入
                if position:
                    # 更新现有持仓
                    total_quantity = position["quantity"] + order.quantity
                    total_cost = position["avg_price"] * position["quantity"] + order.price * order.quantity
                    new_avg_price = total_cost / total_quantity
                    
                    await db_manager.save_position({
                        "strategy_id": order.strategy_id,
                        "symbol": order.symbol,
                        "quantity": total_quantity,
                        "avg_price": new_avg_price,
                        "current_price": order.price,
                        "market_value": total_quantity * order.price,
                        "pnl": (order.price - new_avg_price) * total_quantity,
                        "pnl_rate": (order.price - new_avg_price) / new_avg_price if new_avg_price > 0 else 0
                    })
                else:
                    # 新建持仓
                    await db_manager.save_position({
                        "strategy_id": order.strategy_id,
                        "symbol": order.symbol,
                        "quantity": order.quantity,
                        "avg_price": order.price,
                        "current_price": order.price,
                        "market_value": order.quantity * order.price,
                        "pnl": 0,
                        "pnl_rate": 0
                    })
                    
            else:
                # 卖出
                if position and position["quantity"] >= order.quantity:
                    # 更新持仓
                    new_quantity = position["quantity"] - order.quantity
                    
                    if new_quantity > 0:
                        await db_manager.save_position({
                            "strategy_id": order.strategy_id,
                            "symbol": order.symbol,
                            "quantity": new_quantity,
                            "avg_price": position["avg_price"],
                            "current_price": order.price,
                            "market_value": new_quantity * order.price,
                            "pnl": (order.price - position["avg_price"]) * new_quantity,
                            "pnl_rate": (order.price - position["avg_price"]) / position["avg_price"] if position["avg_price"] > 0 else 0
                        })
                    else:
                        # 清仓
                        await db_manager.save_position({
                            "strategy_id": order.strategy_id,
                            "symbol": order.symbol,
                            "quantity": 0,
                            "avg_price": 0,
                            "current_price": order.price,
                            "market_value": 0,
                            "pnl": 0,
                            "pnl_rate": 0
                        })
            
            logger.info(f"持仓更新完成: {order.symbol} {order.trade_type.value} {order.quantity}")
            
        except Exception as e:
            logger.error(f"更新持仓失败: {e}")
    
    async def cancel_order(self, order_id: str) -> Dict[str, Any]:
        """取消订单"""
        try:
            async with self._lock:
                if order_id not in self.pending_orders:
                    return {
                        "success": False,
                        "error": "订单不存在或已成交"
                    }
                
                order = self.pending_orders[order_id]
                
                # 检查是否可以取消
                if order.status != OrderStatus.PENDING:
                    return {
                        "success": False,
                        "error": f"订单状态为 {order.status.value}，无法取消"
                    }
                
                # 取消订单
                order.status = OrderStatus.CANCELLED
                
                # 移动订单
                del self.pending_orders[order_id]
                self.completed_orders[order_id] = order
            
            # 更新数据库
            await db_manager.save_trade_record({
                "strategy_id": order.strategy_id,
                "order_id": order_id,
                "symbol": order.symbol,
                "trade_type": order.trade_type.value,
                "quantity": order.quantity,
                "price": order.price,
                "amount": order.amount,
                "commission": order.commission,
                "trade_time": order.created_at,
                "status": "cancelled"
            })
            
            logger.info(f"订单 {order_id} 已取消")
            
            return {
                "success": True,
                "order_id": order_id
            }
            
        except Exception as e:
            logger.error(f"取消订单失败: {e}")
            return {
                "success": False,
                "error": str(e)
            }
    
    def get_order_status(self, order_id: str) -> Optional[Dict]:
        """获取订单状态"""
        try:
            # 检查待成交订单
            if order_id in self.pending_orders:
                order = self.pending_orders[order_id]
                return {
                    "order_id": order_id,
                    "status": order.status.value,
                    "symbol": order.symbol,
                    "trade_type": order.trade_type.value,
                    "quantity": order.quantity,
                    "price": order.price,
                    "amount": order.amount,
                    "commission": order.commission,
                    "created_at": order.created_at.isoformat(),
                    "filled_at": order.filled_at.isoformat() if order.filled_at else None
                }
            
            # 检查已完成订单
            if order_id in self.completed_orders:
                order = self.completed_orders[order_id]
                return {
                    "order_id": order_id,
                    "status": order.status.value,
                    "symbol": order.symbol,
                    "trade_type": order.trade_type.value,
                    "quantity": order.quantity,
                    "price": order.price,
                    "amount": order.amount,
                    "commission": order.commission,
                    "created_at": order.created_at.isoformat(),
                    "filled_at": order.filled_at.isoformat() if order.filled_at else None
                }
            
            return None
            
        except Exception as e:
            logger.error(f"获取订单状态失败: {e}")
            return None
    
    def get_all_orders(self, strategy_id: Optional[str] = None) -> List[Dict]:
        """获取所有订单"""
        try:
            all_orders = []
            
            # 待成交订单
            for order in self.pending_orders.values():
                if strategy_id is None or order.strategy_id == strategy_id:
                    all_orders.append({
                        "order_id": order.order_id,
                        "strategy_id": order.strategy_id,
                        "status": order.status.value,
                        "symbol": order.symbol,
                        "trade_type": order.trade_type.value,
                        "quantity": order.quantity,
                        "price": order.price,
                        "amount": order.amount,
                        "commission": order.commission,
                        "created_at": order.created_at.isoformat(),
                        "filled_at": order.filled_at.isoformat() if order.filled_at else None
                    })
            
            # 已完成订单
            for order in self.completed_orders.values():
                if strategy_id is None or order.strategy_id == strategy_id:
                    all_orders.append({
                        "order_id": order.order_id,
                        "strategy_id": order.strategy_id,
                        "status": order.status.value,
                        "symbol": order.symbol,
                        "trade_type": order.trade_type.value,
                        "quantity": order.quantity,
                        "price": order.price,
                        "amount": order.amount,
                        "commission": order.commission,
                        "created_at": order.created_at.isoformat(),
                        "filled_at": order.filled_at.isoformat() if order.filled_at else None
                    })
            
            # 按创建时间排序
            all_orders.sort(key=lambda x: x["created_at"], reverse=True)
            
            return all_orders
            
        except Exception as e:
            logger.error(f"获取所有订单失败: {e}")
            return []


# 全局交易引擎实例
trade_engine = TradeEngine()
